package model;

import java.util.Iterator;
import java.util.List;

/**
 * Deze klasse let op de point of interests (poi) en weet welke poi
 * het dichtste in de buurt is van de gebruiker.
 * Deze klasse is zowel een observer en een observable.
 * Het is een observer omdat deze klasse zich registreert bij een GpsReceiver.
 * Het is een observable omdat deze klasse updates geeft wanneer de
 * meest dichtst bijzijnde poi veranderd.
 */
public class PointOfInterestWatcher extends Observable implements Observer {

    private GpsReceiver gpsReceiver;
    private Route route;
    private AbstractDistanceCalculator distanceCalculator;
    private RouteWaypoint currNearestWaypoint;
    
    public PointOfInterestWatcher(GpsReceiver gpsReceiver, Route route) {
        this.gpsReceiver = gpsReceiver;
        this.gpsReceiver.attach(this);
        this.route = route;
        distanceCalculator = new MetrischDistanceCalculator();
    }
    
    public RouteWaypoint getNextWaypoint() {
        return currNearestWaypoint;
    }
    
    /**
     * Wordt aangeroepen door GpsReceiver wanneer
     * de huidige positie veranderd.
     */
    @Override
    public void update() {
        
        RouteWaypoint nearestWaypoint = getNearestWayPoint();
        
        if (currNearestWaypoint == null) {
            currNearestWaypoint = nearestWaypoint;
        }
        else {        
            int nearestWpSeqNr = nearestWaypoint.getSequenceNumber();
            int currNearestWpSeqNr = currNearestWaypoint.getSequenceNumber();

            // Is dit een ander waypoint? Ja: Notify de observers
            if (nearestWpSeqNr != currNearestWpSeqNr) {
                currNearestWaypoint = nearestWaypoint;
                notifyObservers();
            }
        }
    }
    
    /**
     * Geeft het RouteWaypoint terug van het
     * meest dichtst bijzijnde point of interest.
     * 
     * @param coordinate
     * @return RouteWaypoint van het dichtst bijzijnde pooint of interest
     */
    private RouteWaypoint getNearestWayPoint() {
        
        GpsCoordinate currentPosition = gpsReceiver.getGpsCoordinate();
        RouteWaypoint currentNearestWaypoint = null;
        double nearestWaypointDistance = Double.MAX_VALUE;
        
        List<RouteWaypoint> pointOfInterestWaypoints = route.getPointOfInterests();
        Iterator<RouteWaypoint> itr = pointOfInterestWaypoints.iterator();
        
        while (itr.hasNext()) {
            
            RouteWaypoint poiWaypoint = itr.next();
            double distance = distanceCalculator.getDistance(currentPosition, poiWaypoint.getGpsCoordinate());
            
            if (distance < nearestWaypointDistance) {
                currentNearestWaypoint = poiWaypoint;
                nearestWaypointDistance = distance;
            }
        }
        
        return currentNearestWaypoint;
    }
    
}
